import { FieldData, ValidatedError } from "@arco-design/web-vue/es/form/interface";
import { Component, InjectionKey } from "vue";
import {
  CheckboxGroupInstance,
  ColProps,
  FormItemInstance,
  InputInstance,
  InputNumberInstance,
  InputPasswordInstance,
  InputTagInstance,
  RadioGroupInstance,
  RangePickerInstance,
  SelectInstance,
  SwitchInstance,
  TextareaInstance,
  TreeInstance,
} from "@arco-design/web-vue";

export type FormComponentName =
  | "Text"
  | "Input"
  | "InputPassword"
  | "InputNumber"
  | "InputTag"
  | "RangePicker"
  | "Upload"
  | "Select"
  | "Switch"
  | "CheckboxGroup"
  | "RadioGroup"
  | "Textarea";

export type FormComponent = Exclude<FormComponentName, "Text">;
export type FormValidateCallback = (errors: undefined | Record<string, ValidatedError>) => void;
export type FormValidateReturn = Promise<undefined | Record<string, ValidatedError>>;
export type FormRegister = (methods: FormInjectMethods) => void;
export type FormKey = InjectionKey<any>;
export type RenderComponent = (...args: any[]) => Component;

export interface FormInjectMethods extends FormMethods {
  setFormConfig: (config?: any) => void;
}

export interface FormItem {
  onlyItem?: boolean;
  content?: FormItem[];
  render?: RenderComponent;

  /////////////////////////////////
  label: FormItemInstance["label"];
  field: FormItemInstance["field"];
  component?: FormComponent;
  /////////////////////////////////
  col?: ColProps;
  formItem?: Omit<FormItemInstance["$props"], "label" | "field">;
  placeholder?: string;
  props?:
    | InputInstance["$props"]
    | InputPasswordInstance["$props"]
    | InputTagInstance["$props"]
    | Stringify<InputNumberInstance["$props"], "min" | "max">
    | RangePickerInstance["$props"]
    | SelectInstance["$props"]
    | SwitchInstance["$props"]
    | CheckboxGroupInstance["$props"]
    | RadioGroupInstance["$props"]
    | TextareaInstance["$props"]
    | TreeInstance["$props"];
  options?:
    | SelectInstance["$props"]["options"]
    | RadioGroupInstance["$props"]["options"]
    | CheckboxGroupInstance["$props"]["options"];
  data?: TreeInstance["$props"]["data"];
  rules?: FormItemInstance["$props"]["rules"];
}

export interface FormMethods {
  validate: (callback?: FormValidateCallback) => FormValidateReturn;
  validateField: (field: string | string[], callback: FormValidateCallback) => FormValidateReturn;
  resetField: (field: string | string[]) => void;
  clearValidate: (field: string | string[]) => void;
  setFields: (data: Record<string, FieldData>) => void;
  scrollToField: (field: string) => void;
  getFormValue: <T extends string>() => Record<T, any>;
  setFormValue: (model?: Record<string, any>) => void;
  updateFormItem: (formItemConfig: FormItem | FormItem[]) => void;
}

export interface FormItemType<T = any> extends Partial<FormItemInstance["$props"]> {
  col?: number;
  component?: FormComponent;
  placeholder?: string;
  render?: (model: Ref<T>) => Component;
  props?:
    | InputInstance["$props"]
    | InputPasswordInstance["$props"]
    | InputTagInstance["$props"]
    | Stringify<InputNumberInstance["$props"], "min" | "max">
    | RangePickerInstance["$props"]
    | SelectInstance["$props"]
    | SwitchInstance["$props"]
    | CheckboxGroupInstance["$props"]
    | RadioGroupInstance["$props"]
    | TextareaInstance["$props"]
    | TreeInstance["$props"];
  options?:
    | SelectInstance["$props"]["options"]
    | RadioGroupInstance["$props"]["options"]
    | CheckboxGroupInstance["$props"]["options"];
}
